package cn.hebutrun.oulabot.common.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ModifierUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * bean转化
 *
 * @author libiao@bjca.org.cn
 */
@UtilityClass
public class ObjTransfer {

  /**
   * copy对象并忽略null字段
   *
   * @param from 资源
   * @param clazz 类型
   */
  @SneakyThrows
  public <T> T toObjectIgnoreNull(Object from, Class<T> clazz) {
    if (Objects.isNull(from)) {
      return null;
    }
    return toObject(from, clazz, true);
  }

  @SneakyThrows
  public <T> T toObject(Object from, Class<T> clazz, boolean ignoreNull) {
    if (Objects.isNull(from)) {
      return null;
    }
    T to = clazz.getDeclaredConstructor().newInstance();
    BeanUtil.copyProperties(from, to, CopyOptions.create().setIgnoreNullValue(ignoreNull));
    return to;
  }

  public <T> T toObject(Object from, Class<T> clazz) {
    return toObject(from, clazz, true);
  }

  public <R> List<R> toList(List<?> list, Class<R> rClass) {
    if (CollUtil.isEmpty(list)) {
      return Collections.emptyList();
    }
    return list.stream().map(ele -> toObjectIgnoreNull(ele, rClass)).collect(Collectors.toList());
  }

  /** 对象转下划线Map */
  public Map<String, String> toLowerCaseKeyMap(Object obj, String removeKeyPrefix) {
    final Field[] declaredFields = obj.getClass().getDeclaredFields();
    if (ArrayUtil.isEmpty(declaredFields)) {
      return Collections.emptyMap();
    }

    return Arrays.stream(declaredFields)
        .filter(field -> StrUtil.isNotBlank(field.getName()))
        .filter(field -> !ModifierUtil.isStatic(field))
        .collect(
            Collectors.toMap(
                field -> {
                  final String key = StringUtil.toDBUnderlineCase(field.getName());
                  if (StrUtil.startWith(key, removeKeyPrefix)) {
                    return StrUtil.removePrefix(key, removeKeyPrefix);
                  }
                  return key;
                },
                field -> {
                  try {
                    field.setAccessible(true);
                    return StrUtil.nullToEmpty((String) field.get(obj));
                  } catch (Exception e) {
                    LogUtil.warn("toLowerCaseKeyMap", e);
                    return StrUtil.EMPTY;
                  }
                }));
  }

  public <R> Page<R> toPage(Page<?> page, Class<R> clazz) {
    Page<R> res = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
    res.setRecords(toList(page.getRecords(), clazz));
    return res;
  }

  public <R> Page<R> toPage(Page<?> page, List<R> list) {
    Page<R> res = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
    res.setRecords(list);
    return res;
  }
}
